<?php

/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */

/**
 * Short description for file
 *
 * Long description for file (if any)...
 *
 * PHP version 5
 *
 * Copyright 2008 The Picnic PHP Framework
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * @category      Framework
 * @package       Pfw
 * @author        Sean Sitter <sean@picnicphp.com>
 * @copyright     2008 The Picnic PHP Framework
 * @license       http://www.apache.org/licenses/LICENSE-2.0
 * @link          http://www.picnicphp.com
 * @since         0.10
 */


final class Pfw_Controller_Front
{
    private static $instance = null;
    private $router_inst = null;
    private $cont_act_mapper = null;


    /**
     * Singleton instance
     *
     * @return Pfw_Controller_Front
     */
    public static function getInstance()
    {
        if (null === self::$instance) {
            self::$instance = new self();
        }
        return self::$instance;
    }


    /**
     * Gets an instance of the router, or Pfw_Controller_Router_Standard if none
     *
     * @return Pfw_Controller_Router_Base $router_inst
     */
    public function getRouter()
    {
        if (null === $this->router_inst ){
            Pfw_Loader::loadClass('Pfw_Controller_Router_Standard');
            $this->router_inst = new Pfw_Controller_Router_Standard();
        }
        return $this->router_inst;
    }


    /**
     * Sets the router instance, defaults to Pfw_Controller_Router_Standard
     *
     * @param Pfw_Controller_Router_Base $router_inst
     * @return Pfw_Controller_Router_Base if a router was previously set, true otherwise
     */
    public function setRouter($router_inst)
    {
        if (!is_a($router_inst, 'Pfw_Controller_Router_Base')) {
            throw new Pfw_Exception_Type();
        }
        $old_router = ($this->router_inst === null) ? true : $this->router_inst;
        $this->router_inst = $router_inst;
        return $old_Router;
    }


    public function setMapper($mapper){
        if (!is_a($mapper, 'Pfw_Controller_Mapper_Base')) {
            throw new Pfw_Exception_Dispatch("Mappers must be instances of".
                "Pfw_Controller_Mapper_Base");
        }
        $this->cont_act_mapper = $mapper;
    }


    public function getMapper()
    {
        if (!isset($this->cont_act_mapper)) {
            Pfw_Loader::loadClass('Pfw_Controller_Mapper_Standard');
            $this->cont_act_mapper = new Pfw_Controller_Mapper_Standard();
        }
        return $this->cont_act_mapper;
    }


    /**
     * Routes the request through the router with assigned routes
     *
     * @param array $routes
     */
    public function dispatch()
    {
        Pfw_PluginManager::execPreRoute();
        $route_params = $this->getRouter()->route($_SERVER['SCRIPT_URL']);
        Pfw_Request::setParams($route_params);

        if (empty($route_params)) {
            Pfw_Loader::loadClass('Pfw_Exception_NotFound');
            throw new Pfw_Exception_NotFound();
        }
        Pfw_PluginManager::execPostRoute();

        $module = isset($route_params['module']) ? $route_params['module'] : null;

        Pfw_PluginManager::execPreMap();
        $cont_action = $this->getMapper()->map(
            $route_params['controller'],
            $route_params['action'],
            $module
        );
        Pfw_PluginManager::execPostMap();
        
        Pfw_PluginManager::execPreDispatch();
        $controller = $cont_action['controller'];
        $method = $cont_action['method'];

        $controller->_setFrontController($this);
        $controller->$method();
        Pfw_PluginManager::execPostDispatch();
    }
}
